package chapter3;

import chapter2.Apple;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;

public class MethodRef {
    /**
     * 方法引用
     *  方法引用可以重复使用现有的方法定义 并像Lambda一样传递它们
     *  方法引用可以看出是调用特定方法的Lambda的一种快捷写法
     *  它的基本实现是 Lambda代表的只是"直接调用这个方法" 那最好还是用名称来调用它  而不是描述如何调用它
     */
    public static void main(String[] args) {
        List<Apple> inventory = new ArrayList<>();
        inventory.sort((Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight()));

        /**
         * 使用方法引用
         */
        inventory.sort(Comparator.comparing(Apple::getWeight));

        /**
         * 如何构建方法引用
         *  方法引用主要有三类：
         *      1、指向静态方法的方法引用 例如Integer::parseInt
         *      2、指向任意类型实例方法的方法引用  例如：String::length
         *      3、指向现有对象的实例方法的方法引用
         *          例如有一个局部变量expensiveTransaction 它的类型是Transaction  这个类有一个实例方法getValue
         *          因此可以写成 expensiveTransaction::getValue
         *
         *  语法形式：
         *      1）(args) -> ClassName.staticMethod(args)
         *              ClassName::staticMethod
         *
         *     2）(arg0, rest) -> arg0.instanceMethod(rest) [注：arg0是ClassName类型]
         *              ClassName::instanceMethod
         *
         *     3）(args) -> expr.instanceMethod(args)
         *              expr::instanceMethod
         */

        List<String> str = Arrays.asList("a", "b", "A", "B");
        str.sort((s1, s2) -> s1.compareToIgnoreCase(s2));
        //方法引用
        str.sort(String::compareToIgnoreCase);

        //构造方法的引用
        Supplier<Apple> c1 = Apple::new;

        //如果构造函数是有参的
        //调用了指向Apple(Integer weight)的构造函数引用
        Function<Integer, Apple> c2 = Apple::new;
        Apple a2 = c2.apply(10);

        //如果构造函数具有两个参数
        BiFunction<String, Integer, Apple> c3 = Apple::new;
        Apple a3 = c3.apply("green", 110);
    }
}
